<!DOCTYPE html>
<html>
<head>
    <title>Electrostatics Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="600" height="450"></canvas>

    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // --- Style settings ---
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;
        
        // --- Define coordinates and sizes ---
        const O = { x: 370, y: 200 };
        const R = 140;
        const O_prime = { x: 450, y: 140 };
        const r = 45;
        const Q_pos = { x: 100, y: 200 };
        const pointRadius = 3;

        // --- Helper function to draw an arrowhead ---
        function addArrowHead(ctx, fromx, fromy, tox, toy) {
            const headlen = 10;
            const dx = tox - fromx;
            const dy = toy - fromy;
            const angle = Math.atan2(dy, dx);
            ctx.moveTo(tox, toy);
            ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(tox, toy);
            ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
        }

        // --- 1. Drawing main conductor (outer sphere) ---
        ctx.beginPath();
        ctx.arc(O.x, O.y, R, 0, 2 * Math.PI);
        ctx.stroke();

        // --- 2. Drawing cavity (inner sphere) ---
        ctx.beginPath();
        ctx.arc(O_prime.x, O_prime.y, r, 0, 2 * Math.PI);
        ctx.stroke();

        // --- 3. Drawing points ---
        ctx.font = 'italic 22px Times New Roman';

        // Point Q
        ctx.beginPath();
        ctx.arc(Q_pos.x, Q_pos.y, pointRadius, 0, 2 * Math.PI);
        ctx.fill();
        ctx.fillText('Q', Q_pos.x - 25, Q_pos.y - 5);

        // Point O
        ctx.beginPath();
        ctx.arc(O.x, O.y, pointRadius, 0, 2 * Math.PI);
        ctx.fill();
        ctx.fillText('O', O.x, O.y - 10);

        // Point O'
        ctx.beginPath();
        ctx.arc(O_prime.x, O_prime.y, pointRadius, 0, 2 * Math.PI);
        ctx.fill();
        ctx.fillText("O'", O_prime.x + 10, O_prime.y - 10);

        // --- 4. Drawing lines and dimensions ---
        // Dashed line from Q to O
        ctx.beginPath();
        ctx.setLineDash([5, 5]);
        ctx.moveTo(Q_pos.x, Q_pos.y);
        ctx.lineTo(O.x, O.y);
        ctx.stroke();
        ctx.setLineDash([]); // Reset to solid line

        // Dimension d
        const d_y_pos = 280;
        ctx.beginPath();
        // The line with arrow
        ctx.moveTo(O.x, d_y_pos);
        ctx.lineTo(Q_pos.x, d_y_pos);
        addArrowHead(ctx, O.x, d_y_pos, Q_pos.x, d_y_pos);
        // The vertical ticks
        ctx.moveTo(Q_pos.x, d_y_pos - 10);
        ctx.lineTo(Q_pos.x, d_y_pos + 10);
        ctx.moveTo(O.x, d_y_pos - 10);
        ctx.lineTo(O.x, d_y_pos + 10);
        ctx.stroke();
        ctx.fillText('d', (Q_pos.x + O.x) / 2 - 5, d_y_pos - 10);

        // Dimension R
        const R_angle = -Math.PI / 5;
        const R_end = { x: O.x + R * Math.cos(R_angle), y: O.y + R * Math.sin(R_angle) };
        ctx.beginPath();
        ctx.moveTo(O.x, O.y);
        ctx.lineTo(R_end.x, R_end.y);
        addArrowHead(ctx, O.x, O.y, R_end.x, R_end.y);
        ctx.stroke();
        ctx.fillText('R', (O.x + R_end.x) / 2 + 10, (O.y + R_end.y) / 2);

        // Dimension r
        const r_angle = 3 * Math.PI / 4;
        const r_end = { x: O_prime.x + r * Math.cos(r_angle), y: O_prime.y + r * Math.sin(r_angle) };
        ctx.beginPath();
        ctx.moveTo(O_prime.x, O_prime.y);
        ctx.lineTo(r_end.x, r_end.y);
        addArrowHead(ctx, O_prime.x, O_prime.y, r_end.x, r_end.y);
        ctx.stroke();
        ctx.fillText('r', (O_prime.x + r_end.x) / 2 - 20, (O_prime.y + r_end.y) / 2 - 5);

        // --- 5. Text labels ---
        // Charge labels
        ctx.fillText('q', O_prime.x - 20, O_prime.y + 5);
        ctx.fillText('−q', O_prime.x - 10, O_prime.y + r + 30);
        ctx.fillText('q', O.x - 10, O.y + R + 30);
        
        // Chinese character labels
        ctx.font = '24px KaiTi, sans-serif'; 
        ctx.fillText('导 体', O.x - 110, O.y - 70); // Conductor
        ctx.fillText('孔', O_prime.x + 20, O_prime.y + 25); // Hole/Cavity

    </script>
</body>
</html>